From fcf318367afc583ddcf67aaa29e5bf4280f50f0b Mon Sep 17 00:00:00 2001 From: robertl Date: Fri, 25 Aug 2006 03:54:47 +0000 Subject: [PATCH] Add (crude) support for Garmin Training Center. --- Makefile.in | 2 +- gbser_win.c | 1 + gtrnctr.c | 302 +++++++++++++++++++++++++++++++++++++ vecs.c | 7 + xmldoc/formats/gtrnctr.xml | 17 +++ 5 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 gtrnctr.c create mode 100644 xmldoc/formats/gtrnctr.xml diff --git a/Makefile.in b/Makefile.in index 839cf4af3..59a4e8500 100644 --- a/Makefile.in +++ b/Makefile.in @@ -53,7 +53,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \ tef_xml.o maggeo.o pathaway.o vitosmt.o gdb.o bcr.o coto.o \ ignrando.o stmwpp.o msroute.o cst.o nmn4.o mag_pdb.o compegps.o \ yahoo.o unicsv.o wfff_xml.o garmin_txt.o axim_gpb.o gpssim.o \ - wbt-200.o stmsdf.o + wbt-200.o stmsdf.o gtrnctr.o FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o \ reverse_route.o sort.o stackfilter.o trackfilter.o discard.o \ diff --git a/gbser_win.c b/gbser_win.c index a339cf86a..26b897e84 100644 --- a/gbser_win.c +++ b/gbser_win.c @@ -1,3 +1,4 @@ +#define ERROR_TIMEOUT 0x4321 /* Serial interface - Windows layer. diff --git a/gtrnctr.c b/gtrnctr.c new file mode 100644 index 000000000..ff81ba9a4 --- /dev/null +++ b/gtrnctr.c @@ -0,0 +1,302 @@ +/* + Access Garmin Training Center (Forerunner/Foretracker/Edge) data files. + + Copyright (C) 2006 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include "xmlgeneric.h" + +static FILE *ofd; +static waypoint *wpt_tmp; +static route_head *trk_head; + +#define MYNAME "gtc" + +static +arglist_t gtc_args[] = { + ARG_TERMINATOR +}; +#if 0 +/* Tracks */ +static xg_callback gl_trk_s; +// static xg_callback gl_trk_ident; +static xg_callback gl_trk_pnt_s, gl_trk_pnt_e; +static xg_callback gl_trk_utc; +static xg_callback gl_trk_lat; +static xg_callback gl_trk_long; +static xg_callback gl_trk_alt; + +static xg_tag_mapping gl_map[] = { + { gl_trk_s, cb_start, "/History/Run/Track" }, + { gl_trk_pnt_s,cb_start, "/History/Run/Track/Trackpoint/Position" }, + { gl_trk_pnt_e,cb_end, "/History/Run/Track/Trackpoint/Position" }, + { gl_trk_lat, cb_cdata, "/History/Run/Track/Trackpoint/Position/Latitude" }, + { gl_trk_long, cb_cdata, "/History/Run/Track/Trackpoint/Position/Longitude" }, + { gl_trk_alt, cb_cdata, "/History/Run/Track/Trackpoint/Position/Altitude" }, + { gl_trk_utc, cb_cdata, "/History/Run/Track/Trackpoint/Time" }, + { NULL, 0, NULL} +}; +#endif + +static void +gtc_rd_init(const char *fname) +{ + fatal(MYNAME ": this format does not support reading.\n"); +} + +#if 0 +static void +gtc_read(void) +{ + xml_read(); +} + +static void +gtc_rd_deinit(void) +{ + xml_deinit(); +} +#endif + +static void +gtc_wr_init(const char *fname) +{ + ofd = xfopen(fname, "w", MYNAME); +} + +static void +gtc_wr_deinit(void) +{ + fclose(ofd); +} + +static int gtc_indent_level; +static void +gtc_write_xml(int indent, const char *fmt, ...) +{ + va_list args; + int i; + va_start(args, fmt); + + if (indent < 0) gtc_indent_level--; + + for (i = 0; i < gtc_indent_level; i++) { + fputs(" ", ofd); + } + + vfprintf(ofd, fmt, args); + + if (indent > 0) gtc_indent_level++; + + va_end(args); + +} + +static void +gtc_waypt_pr(const waypoint *wpt) +{ +#if 0 + fprintf(ofd, " \n"); + fprintf(ofd, " \n"); + fprintf(ofd, " %.5f\n", wpt->latitude); + fprintf(ofd, " %.5f\n", wpt->longitude); + if (wpt->altitude != unknown_alt) { + fprintf(ofd, " %.3f\n", wpt->altitude); + } + fprintf(ofd, " \n"); + fprintf(ofd, " "); + xml_write_time(ofd, wpt->creation_time, "Time"); + fprintf(ofd, " \n"); +#else + gtc_write_xml(1, "\n"); + if (wpt->creation_time) { + char time_string[100]; + xml_fill_in_time(time_string, wpt->creation_time, + XML_LONG_TIME); + if (time_string[0]) { + gtc_write_xml(0, "\n", + time_string); + } + } + gtc_write_xml(1, "\n"); + gtc_write_xml(0, "%f\n", wpt->latitude); + gtc_write_xml(0, "%f\n", wpt->latitude); + gtc_write_xml(-1, "\n"); + if (wpt->altitude != unknown_alt) { + gtc_write_xml(0, "%f\n", wpt->altitude); + } + if (wpt->heartrate) { + gtc_write_xml(0, "%d\n", wpt->heartrate); + } + + gtc_write_xml(-1, "\n"); +#endif +} + +static void +gtc_hdr( const route_head *rte) +{ + gtc_write_xml(1,"\n"); +} + +static void +gtc_ftr(const route_head *rte) +{ + gtc_write_xml(-1,"\n"); +} + +static time_t gtc_least_time; +static time_t gtc_most_time; + +static void +gtc_lap_start(const route_head *rte) +{ + gtc_least_time = 0; + gtc_most_time = 0; +} + +static void +gtc_study_lap(const waypoint *wpt) +{ + if (wpt->creation_time && (gtc_least_time == 0)) + gtc_least_time = wpt->creation_time; + + if (wpt->creation_time && (gtc_least_time > wpt->creation_time)) + gtc_least_time = wpt->creation_time; + + if (wpt->creation_time > gtc_most_time) + gtc_most_time = wpt->creation_time; +} + +static void +gtc_fake_hdr(void) +{ + long secs = 0; + if (gtc_least_time && gtc_most_time) { + secs = gtc_most_time - gtc_least_time; + } + gtc_write_xml(0, "%d\n", secs); + gtc_write_xml(0, "0\n"); + gtc_write_xml(0, "0\n"); + gtc_write_xml(0, "0\n"); + gtc_write_xml(0, "0\n"); + gtc_write_xml(0, "Active\n"); + gtc_write_xml(0, "Manual\n"); +} + +void +gtc_write(void) +{ +#if 0 + fprintf(ofd, "\n"); + fprintf(ofd, "\n"); + fprintf(ofd, " \n"); + track_disp_all(gtc_hdr, gtc_ftr, gtc_waypt_pr); + fprintf(ofd, " \n"); + fprintf(ofd, "\n"); +#else + gtc_write_xml(0, "\n"); + gtc_write_xml(1, "\n"); + gtc_write_xml(1, "\n"); + + gtc_write_xml(1, "\n"); + gtc_write_xml(1, "\n"); + + gtc_lap_start(NULL); + track_disp_all(NULL, NULL, gtc_study_lap); + + if (gtc_least_time) { + char time_string[100]; + xml_fill_in_time(time_string, gtc_least_time, XML_LONG_TIME); + gtc_write_xml(1, "\n", time_string); + } else { + gtc_write_xml(1, "\n"); + } + gtc_fake_hdr(); + track_disp_all(gtc_hdr, gtc_ftr, gtc_waypt_pr); + gtc_write_xml(1, "\n"); + gtc_write_xml(-1, "\n"); + gtc_write_xml(-1, "\n"); + gtc_write_xml(0, "\n"); + gtc_write_xml(0, "\n"); + gtc_write_xml(0, "\n"); + + gtc_write_xml(-1, "\n"); + gtc_write_xml(-1, "\n"); + +#endif +} + +void gl_trk_s(const char *args, const char **unused) +{ + trk_head = route_head_alloc(); + track_add_head(trk_head); +} +#if 0 +void gl_trk_ident(const char *args, const char **unused) +{ + trk_head->rte_name = xstrdup(args); +} +#endif + +void gl_trk_pnt_s(const char *args, const char **unused) +{ + wpt_tmp = waypt_new(); +} + +void gl_trk_pnt_e(const char *args, const char **unused) +{ + track_add_wpt(trk_head, wpt_tmp); +} + +void gl_trk_utc(const char *args, const char **unused) +{ + wpt_tmp->creation_time = xml_parse_time(args); +} + +void gl_trk_lat(const char *args, const char **unused) +{ + wpt_tmp->latitude = atof(args); +} + +void gl_trk_long(const char *args, const char **unused) +{ + wpt_tmp->longitude = atof(args); +} + +void gl_trk_alt(const char *args, const char **unused) +{ + wpt_tmp->altitude = atof(args); +} + + + +ff_vecs_t gtc_vecs = { + ff_type_file, + { ff_cap_none, ff_cap_write, ff_cap_none}, + gtc_rd_init, + gtc_wr_init, + NULL, + gtc_wr_deinit, + NULL, + gtc_write, + NULL, + gtc_args, + CET_CHARSET_ASCII, 0 /* CET-REVIEW */ +}; diff --git a/vecs.c b/vecs.c index 81ef27ac1..e39af20c5 100644 --- a/vecs.c +++ b/vecs.c @@ -109,6 +109,7 @@ extern ff_vecs_t xcsv_vecs; extern ff_vecs_t yahoo_vecs; extern ff_vecs_t wbt_svecs; extern ff_vecs_t wbt_fvecs; +extern ff_vecs_t gtc_vecs; static vecs_t vec_list[] = { @@ -593,6 +594,12 @@ vecs_t vec_list[] = { "Dell Axim Navigation System (.gpb) file format", "gpb" }, + { + >c_vecs, + "gtrnctr", + "Garmin Training Center" + "xml" + }, { NULL, NULL, diff --git a/xmldoc/formats/gtrnctr.xml b/xmldoc/formats/gtrnctr.xml new file mode 100644 index 000000000..f59087135 --- /dev/null +++ b/xmldoc/formats/gtrnctr.xml @@ -0,0 +1,17 @@ + +Garmin Training Center is the successor to Garmin' Logbook program +for their workout units. It is a free upgrade. + + +This format is somewhat underachieving in GPSBabel. It is a write-only +format; we never read it. The bigger problem, however, is a fundamental +impedance mismatch between this format and most of what we support. GPSBabel +fundamentally deals in waypoints, tracks, and routes. While we do record +things like heart rate and temperature when we know it, the fundamentals +of Training Center are different - it deals in concepts like laps and calories +which are rather alien to GPSBabel and most of the formats we support. As +such, while we can describe the tracks pretty accurately, things like +calories and heart zone tracking are not supported. + + + -- 2.30.2